package com.xiaoh.dormitoryrepairreportbackend.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoh.dormitoryrepairreportbackend.common.ErrorCode;
import com.xiaoh.dormitoryrepairreportbackend.exception.BusinessException;
import com.xiaoh.dormitoryrepairreportbackend.constant.UserConstant;
import com.xiaoh.dormitoryrepairreportbackend.mapper.GeneralUserMapper;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.GeneralUser;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.UserAdmin;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.UserMaintenance;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.UserStudent;
import com.xiaoh.dormitoryrepairreportbackend.service.GeneralUserService;
import com.xiaoh.dormitoryrepairreportbackend.service.UserAdminService;
import com.xiaoh.dormitoryrepairreportbackend.service.UserMaintenanceService;
import com.xiaoh.dormitoryrepairreportbackend.service.UserStudentService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 统一用户表 服务实现类
 */
@Service
@Slf4j
public class GeneralUserServiceImpl extends ServiceImpl<GeneralUserMapper, GeneralUser>
        implements GeneralUserService {

    /**
     * 盐值，混淆密码
     */
    private static final String SALT = "xiaoh";

    @Resource
    private UserStudentService userStudentService;

    @Resource
    private UserMaintenanceService userMaintenanceService;

    @Resource
    private UserAdminService userAdminService;

    @Override
    public GeneralUser userLogin(String accountName, String password) {
        // 1. 校验参数
        if (StrUtil.hasBlank(accountName, password)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (accountName.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号过短");
        }
        if (password.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码过短");
        }

        // 2. 加密
        String encryptPassword = DigestUtil.md5Hex(SALT + password);
        // 查询用户是否存在
        QueryWrapper<GeneralUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_name", accountName);
        queryWrapper.eq("password", encryptPassword);
        GeneralUser user = this.baseMapper.selectOne(queryWrapper);
        // 用户不存在
        if (user == null) {
            log.info("user login failed, accountName cannot match password");
            throw new BusinessException(ErrorCode.PASSWORD_ERROR, "用户不存在或密码错误");
        }
        return user;
    }

    @Override
    public Long userRegister(GeneralUser generalUser) {
        String accountName = generalUser.getAccountName();
        String password = generalUser.getPassword();
        String email = generalUser.getEmail();
        String phoneNumber = generalUser.getPhoneNumber();

        // 1. 校验
        if (StrUtil.hasBlank(accountName, password, email, phoneNumber)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (accountName.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");
        }
        if (password.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
        }

        // 账户不能重复
        QueryWrapper<GeneralUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_name", accountName);
        long count = this.baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "账号重复");
        }

        // 邮箱不能重复
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        count = this.baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "邮箱重复");
        }

        // 手机号不能重复
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone_number", phoneNumber);
        count = this.baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "手机号重复");
        }

        // 2. 加密
        String encryptPassword = DigestUtil.md5Hex(SALT + password);
        generalUser.setPassword(encryptPassword);

        // 3. 插入数据
        boolean saveResult = this.save(generalUser);
        if (!saveResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
        }
        return generalUser.getId();
    }

    @Override
    public GeneralUser getUserByAccountName(String accountName) {
        if (StrUtil.isBlank(accountName)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号为空");
        }
        QueryWrapper<GeneralUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_name", accountName);
        return this.getOne(queryWrapper);
    }

    @Override
    public GeneralUser getUserByEmail(String email) {
        if (StrUtil.isBlank(email)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱为空");
        }
        QueryWrapper<GeneralUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        return this.getOne(queryWrapper);
    }

    @Override
    public GeneralUser getUserByPhoneNumber(String phoneNumber) {
        if (StrUtil.isBlank(phoneNumber)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号为空");
        }
        QueryWrapper<GeneralUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone_number", phoneNumber);
        return this.getOne(queryWrapper);
    }

    @Override
    public boolean updateUserInfo(Long userId, String nickName, String email, String phoneNumber) {
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户ID不能为空");
        }

        GeneralUser user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }

        // 检查邮箱是否已被其他用户使用
        if (StrUtil.isNotBlank(email) && !email.equals(user.getEmail())) {
            GeneralUser existingUser = getUserByEmail(email);
            if (existingUser != null && !existingUser.getId().equals(userId)) {
                throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "邮箱已被其他用户使用");
            }
        }

        // 检查手机号是否已被其他用户使用
        if (StrUtil.isNotBlank(phoneNumber) && !phoneNumber.equals(user.getPhoneNumber())) {
            GeneralUser existingUser = getUserByPhoneNumber(phoneNumber);
            if (existingUser != null && !existingUser.getId().equals(userId)) {
                throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "手机号已被其他用户使用");
            }
        }

        // 更新用户信息
        if (StrUtil.isNotBlank(nickName)) {
            user.setNickName(nickName);
        }
        if (StrUtil.isNotBlank(email)) {
            user.setEmail(email);
        }
        if (StrUtil.isNotBlank(phoneNumber)) {
            user.setPhoneNumber(phoneNumber);
        }

        return this.updateById(user);
    }

    @Override
    public boolean updatePassword(Long userId, String oldPassword, String newPassword) {
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户ID不能为空");
        }
        if (StrUtil.hasBlank(oldPassword, newPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码不能为空");
        }
        if (newPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "新密码长度不能少于8位");
        }

        GeneralUser user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }

        // 验证原密码
        String encryptOldPassword = DigestUtil.md5Hex(SALT + oldPassword);
        if (!encryptOldPassword.equals(user.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "原密码错误");
        }

        // 加密新密码
        String encryptNewPassword = DigestUtil.md5Hex(SALT + newPassword);
        user.setPassword(encryptNewPassword);

        return this.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean adminUpdateUserInfo(Long userId, String nickName, String email, String phoneNumber, Integer userType, String dormitoryName) {
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户ID不能为空");
        }

        GeneralUser user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }

        Integer oldUserType = user.getUserType();

        // 检查邮箱是否已被其他用户使用
        if (StrUtil.isNotBlank(email) && !email.equals(user.getEmail())) {
            GeneralUser existingUser = getUserByEmail(email);
            if (existingUser != null && !existingUser.getId().equals(userId)) {
                throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "邮箱已被其他用户使用");
            }
        }

        // 检查手机号是否已被其他用户使用
        if (StrUtil.isNotBlank(phoneNumber) && !phoneNumber.equals(user.getPhoneNumber())) {
            GeneralUser existingUser = getUserByPhoneNumber(phoneNumber);
            if (existingUser != null && !existingUser.getId().equals(userId)) {
                throw new BusinessException(ErrorCode.USER_ALREADY_EXIST, "手机号已被其他用户使用");
            }
        }

        // 更新基本用户信息
        if (StrUtil.isNotBlank(nickName)) {
            user.setNickName(nickName);
        }
        if (StrUtil.isNotBlank(email)) {
            user.setEmail(email);
        }
        if (StrUtil.isNotBlank(phoneNumber)) {
            user.setPhoneNumber(phoneNumber);
        }
        if (userType != null && userType > 0 && userType <= 3) {
            user.setUserType(userType);
        }

        boolean updateResult = this.updateById(user);
        if (!updateResult) {
            return false;
        }

        // 如果用户类型发生变化，需要处理扩展表
        if (userType != null && !userType.equals(oldUserType)) {
            handleUserTypeChange(userId, oldUserType, userType, dormitoryName);
        } else if (userType != null && userType.equals(UserConstant.UserType.STUDENT) && StrUtil.isNotBlank(dormitoryName)) {
            // 如果是学生用户且提供了宿舍地址，更新宿舍信息
            userStudentService.updateDormitoryName(userId, dormitoryName);
        }

        return true;
    }

    /**
     * 处理用户类型变更
     */
    private void handleUserTypeChange(Long userId, Integer oldUserType, Integer newUserType, String dormitoryName) {
        // 删除旧的扩展信息
        if (oldUserType != null) {
            switch (oldUserType) {
                case UserConstant.UserType.STUDENT:
                    userStudentService.removeById(userId);
                    break;
                case UserConstant.UserType.MAINTENANCE:
                    userMaintenanceService.removeById(userId);
                    break;
                case UserConstant.UserType.ADMIN:
                    userAdminService.removeById(userId);
                    break;
            }
        }

        // 创建新的扩展信息
        switch (newUserType) {
            case UserConstant.UserType.STUDENT:
                UserStudent userStudent = new UserStudent();
                userStudent.setUserId(userId);
                userStudent.setDormitoryName(StrUtil.isNotBlank(dormitoryName) ? dormitoryName : "未设置");
                userStudentService.save(userStudent);
                break;
            case UserConstant.UserType.MAINTENANCE:
                UserMaintenance userMaintenance = new UserMaintenance();
                userMaintenance.setUserId(userId);
                userMaintenanceService.save(userMaintenance);
                break;
            case UserConstant.UserType.ADMIN:
                UserAdmin userAdmin = new UserAdmin();
                userAdmin.setUserId(userId);
                userAdminService.save(userAdmin);
                break;
        }
    }
}
